/*
 * EnigmaGM - A feature rich guild management system.
 * Copyright (C) 2007 ajiaojr.
 * 
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
 * 02110-1301, USA.
 */
package org.ajiaojr.enigmagm.client.section;

import org.ajiaojr.enigmagm.client.Paged;
import org.ajiaojr.enigmagm.client.SortablePaged;
import org.ajiaojr.enigmagm.client.data.Item;
import org.ajiaojr.enigmagm.client.data.Point;
import org.ajiaojr.enigmagm.client.data.Raid;
import org.ajiaojr.enigmagm.client.dialog.CharacterDetailsDialog;
import org.ajiaojr.enigmagm.client.dialog.ItemDetailsDialog;
import org.ajiaojr.enigmagm.client.dialog.RaidDetailsDialog;
import org.ajiaojr.enigmagm.client.service.ItemService;
import org.ajiaojr.enigmagm.client.service.ItemServiceAsync;
import org.ajiaojr.enigmagm.client.service.PointService;
import org.ajiaojr.enigmagm.client.service.PointServiceAsync;
import org.ajiaojr.enigmagm.client.service.RaidService;
import org.ajiaojr.enigmagm.client.service.RaidServiceAsync;
import org.ajiaojr.enigmagm.client.widget.PointSystemsListBox;

import com.google.gwt.core.client.GWT;
import com.google.gwt.i18n.client.DateTimeFormat;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.ChangeListener;
import com.google.gwt.user.client.ui.Frame;
import com.google.gwt.user.client.ui.Grid;
import com.google.gwt.user.client.ui.HasHorizontalAlignment;
import com.google.gwt.user.client.ui.HasVerticalAlignment;
import com.google.gwt.user.client.ui.HorizontalPanel;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.ListBox;
import com.google.gwt.user.client.ui.Panel;
import com.google.gwt.user.client.ui.SourcesTabEvents;
import com.google.gwt.user.client.ui.SourcesTableEvents;
import com.google.gwt.user.client.ui.TabListener;
import com.google.gwt.user.client.ui.TabPanel;
import com.google.gwt.user.client.ui.TableListener;
import com.google.gwt.user.client.ui.VerticalPanel;
import com.google.gwt.user.client.ui.Widget;

import java.util.List;

/**
 * Section for displaying point system details.
 * 
 * @author ajiaojr
 */
public class PointSystemsSection extends Section {
  private DateTimeFormat dateTimeFormat =
      DateTimeFormat.getFormat("dd MMM yyyy HH:mm");

  private class ItemsGrid extends SortablePaged {
    public static final int MAX_RESULTS = 30;

    private ItemsGrid(Panel panel) {
      super(panel, MAX_RESULTS, "item_name");
    }

    public void populate() {
      ItemServiceAsync itemService = ItemService.Util.getInstance();

      itemService.findByPointSystemID(currentPointSystemId, sortAttribute,
          ascending, firstResult, maxResults, new AsyncCallback() {

            public void onFailure(Throwable caught) {
              Window.alert(caught.getMessage());
            }

            public void onSuccess(Object result) {
              panel.clear();

              final List items = (List) result;
              int itemsCount = items.size();

              Grid grid = new Grid(itemsCount + 1, 3);
              grid.setWidth("100%");
              grid.addStyleName("gwt-table");
              grid.addStyleName("dataTable");
              grid.setText(0, 0, messages.tabs_items_name());
              grid.setText(0, 1, messages.tabs_items_quality());
              grid.setText(0, 2, messages.tabs_items_value());
              grid.getRowFormatter().addStyleName(0, "header");
              grid.getRowFormatter().addStyleName(0, "clickable");
              grid.getColumnFormatter().setWidth(0, "280px");
              grid.getColumnFormatter().setWidth(1, "100px");
              grid.addTableListener(new TableListener() {

                public void onCellClicked(SourcesTableEvents sender, int row,
                    int cell) {
                  if (row == 0) {
                    switch (cell) {
                      case 0:
                        setSortAttribute("item_name");
                        break;
                      case 1:
                        setSortAttribute("item_quality_name");
                        break;
                      case 2:
                        setSortAttribute("value");
                        break;
                    }
                  } else {
                    Item item = (Item) items.get(row - 1);
                    ItemDetailsDialog idd = new ItemDetailsDialog(item);
                    idd.show();
                  }
                }
              });

              for (int i = 0; i < itemsCount; i++) {
                Item r = (Item) items.get(i);

                int currentRow = i + 1;
                grid.setText(currentRow, 0, r.getItemName());

                grid.setText(currentRow, 1, r.getItemQuality());
                grid.setText(currentRow, 2, Double.toString(r.getValue()));
                grid.getRowFormatter().addStyleName(currentRow, "clickable");
                grid.getRowFormatter().addStyleName(currentRow, "highlight");
              }

              panel.add(grid);
              attachNavBar();
            }
          });
    }
  }

  private class PointsGrid extends SortablePaged {

    public static final int MAX_RESULTS = 40;

    public PointsGrid(Panel parent) {
      super(parent, MAX_RESULTS, "character_name");
    }

    public void populate() {
      PointServiceAsync pointService = PointService.Util.getInstance();

      pointService.findByPointSystemID(currentPointSystemId, sortAttribute,
          ascending, firstResult, maxResults, new AsyncCallback() {

            public void onFailure(Throwable caught) {
              Window.alert(caught.getMessage());
            }

            public void onSuccess(Object result) {
              panel.clear();

              final List points = (List) result;
              int pointsCount = points.size();

              Grid grid = new Grid(pointsCount + 1, 6);
              grid.setWidth("100%");
              grid.setStyleName("gwt-table");
              grid.addStyleName("dataTable");
              grid.setText(0, 0, messages.tabs_points_characterName());
              grid.setText(0, 1, messages.tabs_points_characterClass());
              grid.setText(0, 2, messages.tabs_points_current());
              grid.setText(0, 3, messages.tabs_points_earned());
              grid.setText(0, 4, messages.tabs_points_spent());
              grid.setText(0, 5, messages.tabs_points_adjustment());
              grid.getRowFormatter().addStyleName(0, "header");
              grid.getRowFormatter().addStyleName(0, "clickable");
              grid.getColumnFormatter().setWidth(0, "140px");
              grid.getColumnFormatter().setWidth(1, "100px");
              grid.getColumnFormatter().setWidth(2, "100px");
              grid.getColumnFormatter().setWidth(3, "100px");
              grid.getColumnFormatter().setWidth(4, "100px");
              grid.addTableListener(new TableListener() {

                public void onCellClicked(SourcesTableEvents sender, int row,
                    int cell) {
                  if (row == 0) {
                    switch (cell) {
                      case 0:
                        setSortAttribute("character_name");
                        break;
                      case 1:
                        setSortAttribute("class_name");
                        break;
                      case 2:
                        setSortAttribute("current");
                        break;
                      case 3:
                        setSortAttribute("earned");
                        break;
                      case 4:
                        setSortAttribute("spent");
                        break;
                      case 5:
                        setSortAttribute("adjustment");
                        break;
                    }
                  } else {
                    CharacterDetailsDialog cdd =
                        new CharacterDetailsDialog(
                            ((Point) points.get(row - 1)).getCharacterID());
                    cdd.show();
                  }
                }
              });

              for (int i = 0; i < pointsCount; i++) {
                Point point = (Point) points.get(i);

                int currentRow = i + 1;
                grid.setText(currentRow, 0, point.getCharacterName());
                grid.setText(currentRow, 1, point.getCharacterClassName());
                grid
                    .setText(currentRow, 2, Double.toString(point.getCurrent()));
                grid.setText(currentRow, 3, Double.toString(point.getEarned()));
                grid.setText(currentRow, 4, Double.toString(point.getSpent()));
                grid.setText(currentRow, 5, Double.toString(point
                    .getAdjustment()));
                grid.getRowFormatter().addStyleName(currentRow, "highlight");
                grid.getRowFormatter().addStyleName(currentRow, "clickable");
              }

              panel.add(grid);
              attachNavBar();
            }
          });
    }
  }

  private class RaidsGrid extends Paged {
    public static final int MAX_RESULTS = 30;

    private RaidServiceAsync raidService = RaidService.Util.getInstance();

    private RaidsGrid(Panel parent) {
      super(parent, MAX_RESULTS);
    }

    public void populate() {
      raidService.findByPointSystemID(currentPointSystemId, firstResult,
          maxResults, new AsyncCallback() {

            public void onFailure(Throwable caught) {
              Window.alert(caught.getMessage());
            }

            public void onSuccess(Object result) {
              panel.clear();

              final List raids = (List) result;
              int raidsCount = raids.size();

              Grid grid = new Grid(raidsCount + 1, 3);
              grid.setWidth("100%");
              grid.addStyleName("gwt-table");
              grid.addStyleName("dataTable");
              grid.setText(0, 0, messages.tabs_raids_name());
              grid.setText(0, 1, messages.tabs_raids_time());
              grid.setText(0, 2, messages.tabs_raids_comments());
              grid.getRowFormatter().addStyleName(0, "header");
              grid.getColumnFormatter().setWidth(0, "200px");
              grid.getColumnFormatter().setWidth(1, "200px");
              grid.addTableListener(new TableListener() {

                public void onCellClicked(SourcesTableEvents sender, int row,
                    int cell) {
                  if (row < 1)
                    return;
                  Raid r = (Raid) raids.get(row - 1);
                  RaidDetailsDialog rdd = new RaidDetailsDialog(r);
                  rdd.show();
                }
              });

              for (int i = 0; i < raidsCount; i++) {
                Raid r = (Raid) raids.get(i);

                int currentRow = i + 1;
                grid.setText(currentRow, 0, r.getRaidInstanceName());

                grid.setText(currentRow, 1, dateTimeFormat.format(r
                    .getRaidTimeAsDate()));
                grid.setText(currentRow, 2, r.getComments());
                grid.getRowFormatter().addStyleName(currentRow, "clickable");
                grid.getRowFormatter().addStyleName(currentRow, "highlight");
              }

              panel.add(grid);
              attachNavBar();
            }
          });
    }
  }

  private static PointSystemsSection instance = new PointSystemsSection();

  public static PointSystemsSection getInstance() {
    return instance;
  }

  private int currentPointSystemId = 0;

  private ItemsGrid itemsGrid;

  private PointSystemsSectionMessages messages =
      (PointSystemsSectionMessages) GWT
          .create(PointSystemsSectionMessages.class);

  private PointsGrid pointsGrid;

  private ListBox pointSystemsListBox;

  private RaidsGrid raidsGrid;

  private TabPanel tabPanel;

  private PointSystemsSection() {

    final HorizontalPanel mainPanel = new HorizontalPanel();
    initWidget(mainPanel);
    mainPanel.setWidth("100%");

    final VerticalPanel verticalPanel = new VerticalPanel();
    mainPanel.add(verticalPanel);
    mainPanel.setCellVerticalAlignment(verticalPanel,
        HasVerticalAlignment.ALIGN_TOP);
    verticalPanel.setWidth("100%");
    verticalPanel.setSpacing(6);

    Frame adFrame = new Frame(GWT.getModuleBaseURL() + "/ad.html");
    adFrame.setSize("200px", "350px");
    adFrame.setStyleName("adBox");

    mainPanel.add(adFrame);
    mainPanel.setCellVerticalAlignment(adFrame, HasVerticalAlignment.ALIGN_TOP);
    mainPanel.setCellHorizontalAlignment(adFrame,
        HasHorizontalAlignment.ALIGN_CENTER);
    mainPanel.setCellWidth(adFrame, "140px");

    final HorizontalPanel horizontalPanel = new HorizontalPanel();
    verticalPanel.add(horizontalPanel);
    horizontalPanel.setSpacing(5);
    horizontalPanel.setVerticalAlignment(HasVerticalAlignment.ALIGN_MIDDLE);

    final Label pointSystemLabel = new Label(messages.pointSystem());
    horizontalPanel.add(pointSystemLabel);

    pointSystemsListBox = new PointSystemsListBox();
    horizontalPanel.add(pointSystemsListBox);
    pointSystemsListBox.addChangeListener(new ChangeListener() {
      public void onChange(Widget sender) {
        int selectionIndex = pointSystemsListBox.getSelectedIndex();
        int value =
            Integer.parseInt(pointSystemsListBox.getValue(selectionIndex));
        if (value != 0 && value != currentPointSystemId) {
          currentPointSystemId = value;
          refreshTabs();
        }
      }
    });

    tabPanel = new TabPanel();
    verticalPanel.add(tabPanel);
    tabPanel.addTabListener(new TabListener() {
      public boolean onBeforeTabSelected(SourcesTabEvents sender, int tabIndex) {
        return true;
      }

      public void onTabSelected(SourcesTabEvents sender, int tabIndex) {
        refreshTabs();
      }
    });
    tabPanel.setWidth("100%");
    verticalPanel.setCellVerticalAlignment(tabPanel,
        HasVerticalAlignment.ALIGN_TOP);

    final VerticalPanel pointsPanel = new VerticalPanel();
    tabPanel.add(pointsPanel, messages.tabs_points());
    pointsPanel.setSpacing(5);
    pointsPanel.setWidth("100%");

    final VerticalPanel pointsGridContainer = new VerticalPanel();
    pointsPanel.add(pointsGridContainer);
    pointsGridContainer.setWidth("100%");
    pointsGrid = new PointsGrid(pointsGridContainer);

    final Label pointsHintLabel =
        new Label(messages.tip(messages.tabs_points_tip()));
    pointsPanel.add(pointsHintLabel);
    pointsHintLabel.setStyleName("tip");
    pointsPanel.setCellHorizontalAlignment(pointsHintLabel,
        HasHorizontalAlignment.ALIGN_LEFT);

    final VerticalPanel raidsContainer = new VerticalPanel();
    tabPanel.add(raidsContainer, messages.tabs_raids());
    raidsContainer.setSpacing(5);

    final VerticalPanel raidGridContainer = new VerticalPanel();
    raidsGrid = new RaidsGrid(raidGridContainer);
    raidsContainer.add(raidGridContainer);
    raidGridContainer.setWidth("100%");

    final Label raidsHintLabel =
        new Label(messages.tip(messages.tabs_raids_tip()));
    raidsContainer.add(raidsHintLabel);
    raidsHintLabel.setStyleName("tip");

    final VerticalPanel itemsContainer = new VerticalPanel();
    tabPanel.add(itemsContainer, messages.tabs_items());
    itemsContainer.setSpacing(5);
    itemsContainer.setWidth("100%");

    final VerticalPanel itemGridContainer = new VerticalPanel();
    itemsGrid = new ItemsGrid(itemGridContainer);
    itemsContainer.add(itemGridContainer);
    itemGridContainer.setWidth("100%");

    tabPanel.selectTab(0);
  }

  public String getName() {
    return messages.section_name();
  }

  private void refreshTabs() {
    if (currentPointSystemId == 0) {
      return;
    }

    switch (tabPanel.getTabBar().getSelectedTab()) {
      case 0: // refresh points;
        pointsGrid.populate();
        break;
      case 1: // refresh raids;
        raidsGrid.populate();
        break;
      case 2: // refresh items;
        itemsGrid.populate();
    }
  }
}
